#include "systemrestore.h"
#include <QLabel>
#include <QPushButton>
#include <QComboBox>
#include <QCheckBox>
#include <QMovie>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <unistd.h>

#include "../component/circlelabel.h"
#include "../component/mycheckbox.h"
#include "../component/myiconlabel.h"
#include "../component/mylabel.h"
#include "../component/mylineedit.h"
#include "../component/mypushbutton.h"
#include "../component/linelabel.h"
#include "../component/ringsprogressbar.h"
#include "../component/pixmaplabel.h"
#include "../../common/utils.h"
#include "../globalbackupinfo.h"
#include "../gsettingswrapper.h"
#include "messageboxutils.h"
#include "selectrestorepoint.h"
#include "kborderbutton.h"

using namespace kdk;
// bigTitle控件前面的宽度：24+spacing
#define LEN_TITLE_PRE 50
// labelCheck1、labelCheck2控件前面的宽度：10+6+5
#define LEN_DOT_PRE 50

SystemRestore::SystemRestore(QWidget *parent) :
    QStackedWidget(parent)
{
    m_isRetainUserData = false;
    m_isFactoryRestore = false;
    m_pInterface = nullptr;
    m_iPosition = BackupPosition::LOCAL;

    // 界面手写代码创建，作为练手
    initFirstWidget();
    initSecondWidget();
    initThirdWidget();
    initLastWidget();
}

SystemRestore::~SystemRestore()
{
    delete m_pInterface;
    m_pInterface = nullptr;
}

/**
 * @brief 初始化第一个页面
 */
void SystemRestore::initFirstWidget()
{
    QWidget *first = new QWidget;
    QVBoxLayout *vLayout = new QVBoxLayout;
    vLayout->addStretch();

    // 中部布局包含一个独立的窗口，用于大小变化时局部相对不变
    QWidget *center = new QWidget;
    center->setFixedSize(760, 540);
    QHBoxLayout *centerHBoxLayout = new QHBoxLayout;
    centerHBoxLayout->addStretch();
    centerHBoxLayout->addWidget(center);
    centerHBoxLayout->addStretch();
    vLayout->addLayout(centerHBoxLayout);
    // 图片
    PixmapLabel *imageRestore_firstPage = new PixmapLabel(center);
    imageRestore_firstPage->setGeometry(421, 120, 300, 326);
    imageRestore_firstPage->setScaledContents(true);
    imageRestore_firstPage->setLightAndDarkPixmap(":/images/system_restore.png", ":/images/system_restore_dark.png");

    // 系统还原大字提示
    MyLabel *labelRestore_firstPage = new MyLabel(center);
    labelRestore_firstPage->setDeplayText(tr("System Restore"));
    labelRestore_firstPage->setFixedWidth(500);
    labelRestore_firstPage->setFixedHeight(48);
    labelRestore_firstPage->move(41, 120);
    QFont font;
    font.setBold(true);
    font.setPixelSize(36);
    labelRestore_firstPage->setFont(font);
    // labelRestore_firstPage->setAttribute(Qt::WA_TranslucentBackground);
    labelRestore_firstPage->setScaledContents(true);
    labelRestore_firstPage->adjustSize();

    // 系统还原说明
    MyLabel *labelNote_firstPage = new MyLabel(center);
    labelNote_firstPage->setFixedWidth(700);
    labelNote_firstPage->setFixedHeight(24);
    labelNote_firstPage->move(41, 180);
    // 在您遇到问题时可将系统还原到以前的状态
    labelNote_firstPage->setDeplayText(tr("You can restore the system to its previous state"));
    font.setBold(false);
    font.setPixelSize(18);
    labelNote_firstPage->setFont(font);
    labelNote_firstPage->setScaledContents(true);
    labelNote_firstPage->adjustSize();

    // 操作简单
    MyIconLabel *iconSimple_firstPage = new MyIconLabel(center);
    iconSimple_firstPage->setGeometry(41, 244, 210, 36);
    iconSimple_firstPage->setThemeIcon("ukui-bf-simple-symbolic", ":/symbos/ukui-bf-simple-symbolic");
    iconSimple_firstPage->setDesplayText(tr("Simple"));
    iconSimple_firstPage->setEnabled(false);

    // 安全可靠
    MyIconLabel *iconSecurity_firstPage = new MyIconLabel(center);
    iconSecurity_firstPage->setGeometry(231, 244, 180, 36);
    iconSecurity_firstPage->setThemeIcon("ukui-bf-security-symbolic", ":/symbos/ukui-bf-security-symbolic");
    iconSecurity_firstPage->setDesplayText(tr("Security"));
    iconSecurity_firstPage->setEnabled(false);

    // 修复系统损坏
    MyIconLabel *iconMultiBackup_firstPage = new MyIconLabel(center);
    iconMultiBackup_firstPage->setGeometry(41, 296, 210, 36);
    iconMultiBackup_firstPage->setThemeIcon("ukui-bf-damage-symbolic", ":/symbos/ukui-bf-damage-symbolic");
    iconMultiBackup_firstPage->setDesplayText(tr("Repair"));
    iconMultiBackup_firstPage->setEnabled(false);

    // 自主操作
    MyIconLabel *iconSmallSize_firstPage = new MyIconLabel(center);
    iconSmallSize_firstPage->setGeometry(231, 296, 180, 36);
    iconSmallSize_firstPage->setThemeIcon("ukui-self-help-symbolic", ":/symbos/ukui-self-help-symbolic");
    iconSmallSize_firstPage->setDesplayText(tr("Independent"));
    iconSmallSize_firstPage->setEnabled(false);

    // 开始还原按钮
    MyPushButton *beginRestore = new MyPushButton(center);
    beginRestore->setGeometry(41, 372, 180, 52);
    beginRestore->setText(tr("Start Restore"));
    beginRestore->setEnabled(true);
    beginRestore->setAutoRepeat(true);
    beginRestore->setProperty("isImportant", true);
    font.setPixelSize(24);
    beginRestore->setFont(font);
    connect(beginRestore, &MyPushButton::clicked, this, &SystemRestore::on_button_beginRestore_clicked);

    // 底部控件布局
    QHBoxLayout *bottomHBoxLayout = new QHBoxLayout;
    bottomHBoxLayout->addStretch();
    // 恢复出厂复选框
    MyCheckBox * checkFactoryRestore = new MyCheckBox(tr("Factory Restore"));
    if (!Utils::isHuawei990())
        checkFactoryRestore->setVisible(false);
    // 保留用户数据复选框
    MyCheckBox * retainUserData = new MyCheckBox(tr("Retaining User Data"));
    bottomHBoxLayout->addWidget(checkFactoryRestore);
    bottomHBoxLayout->addSpacing(16);
    bottomHBoxLayout->addWidget(retainUserData);
    bottomHBoxLayout->addSpacing(40);
    bottomHBoxLayout->setAlignment(Qt::AlignRight);

    vLayout->addStretch();
    vLayout->addLayout(bottomHBoxLayout);
    vLayout->addSpacing(20);
    first->setLayout(vLayout);

    connect(checkFactoryRestore, &MyCheckBox::stateChanged, this, [=](int state) {
        this->m_isFactoryRestore = Qt::Unchecked == state ? false : true;
        if (this->m_isFactoryRestore) {
            retainUserData->setChecked(false);
        }
    });
    connect(retainUserData, &MyCheckBox::stateChanged, this, [=](int state) {
        this->m_isRetainUserData = Qt::Unchecked == state ? false : true;
        if (this->m_isRetainUserData) {
            checkFactoryRestore->setChecked(false);
        }
    });

    addWidget(first);
}

/**
 * @brief “上一步”按钮响应槽
 * @param checked
 */
void SystemRestore::on_pre_clicked(bool checked)
{
    Q_UNUSED(checked)
    int index = this->currentIndex() - 1;
    if (index >= 0) {
        this->setCurrentIndex(index);
    }
}

/**
 * @brief “下一步”按钮响应槽
 * @param checked
 */
void SystemRestore::on_next_clicked(bool checked)
{
    Q_UNUSED(checked)
    int index = this->currentIndex() + 1;
    if (index < this->count()) {
        this->setCurrentIndex(index);
    }
}

/**
 * @brief “开始还原”按钮响应槽
 * @param checked
 */
void SystemRestore::on_button_beginRestore_clicked(bool checked)
{
    Q_UNUSED(checked)

    this->m_uuid = "";
    this->m_devPath = "";
    this->m_backupName = "";
    this->m_isOtherMachine = false;
    this->m_iPosition = BackupPosition::LOCAL;

    // 出厂还原，不用去选择备份点
    if (m_isFactoryRestore) {
        // 出厂还原后，用户数据将会丢失
        if (!MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(this, QObject::tr("Warning"),
                                                          QObject::tr("Restore factory settings, your system user data will not be retained. Are you sure to continue?"),
                                                          QObject::tr("Continue"), QObject::tr("Cancel"))) {
            return;
        }

        //出厂还原
        m_uuid = FACTORY_BACKUP_UUID;
        m_devPath = "";
        this->m_backupName = "";
        this->m_isOtherMachine = false;
    } else {
        // 系统备份点列表中选择备份点
        SelectRestorePoint *selectRestoreDialog = new SelectRestorePoint(this);
        connect(selectRestoreDialog, &SelectRestorePoint::selected, this, [=](ParseBackupList::BackupPoint backupPoint){
            this->m_uuid = backupPoint.m_uuid;
            this->m_devPath = backupPoint.m_path;
            this->m_backupName = backupPoint.m_backupName;
            this->m_isOtherMachine = backupPoint.m_iPosition == BackupPosition::OTHER ? true : false;
            this->m_iPosition = backupPoint.m_iPosition == BackupPosition::OTHER ? BackupPosition::UDISK : backupPoint.m_iPosition;
        });

        if (QDialog::Rejected == selectRestoreDialog->exec()) {
            selectRestoreDialog->deleteLater();
            return ;
        }
        selectRestoreDialog->deleteLater();
    }

    on_next_clicked();
    emit this->startCheckEnv();
}

/**
 * @brief 初始化第二界面--检测中
 */
void SystemRestore::initSecondWidget()
{
    QWidget *second = new QWidget;

    // 流程进度提示栏
    CircleLable *one = new CircleLable("1", second, 24, QColor(COLOR_BLUE));
    LineLabel *line1 = new LineLabel(second, QColor(COLOR_BLUE));
    CircleLable *two = new CircleLable("2", second);
    LineLabel *line2 = new LineLabel(second, QColor(COLOR_GRAY));
    CircleLable *three = new CircleLable("3", second);
    QHBoxLayout *layoutLine1 = new QHBoxLayout;
    layoutLine1->addSpacing(128);
    layoutLine1->addWidget(one);
    layoutLine1->addWidget(line1);
    layoutLine1->addWidget(two);
    layoutLine1->addWidget(line2);
    layoutLine1->addWidget(three);
    layoutLine1->addSpacing(128);

    MyLabel *label1 = new MyLabel(tr("checking"), second);
    label1->setIsOriginal(true);
    label1->setFontColor(QColor(COLOR_BLUE));
    label1->setFixedWidth(164);
    MyLabel *label2 = new MyLabel(tr("restoring"), second);
    label2->setIsOriginal(true);
    label2->setEnabled(false);
    label2->setFixedWidth(164);
    MyLabel *label3 = new MyLabel(tr("finished"), second);
    label3->setIsOriginal(true);
    label3->setEnabled(false);
    label3->setFixedWidth(164);
    QHBoxLayout *layoutLine2 = new QHBoxLayout;
    layoutLine2->addSpacing(54);
    layoutLine2->addWidget(label1);
    layoutLine2->addStretch();
    layoutLine2->addWidget(label2);
    layoutLine2->addStretch();
    layoutLine2->addWidget(label3);
    layoutLine2->addSpacing(54);

    // ------------ 中部布局begin-------------
    QWidget *centerFont = new QWidget(second);
    centerFont->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    QVBoxLayout *vlayoutCenterFont = new QVBoxLayout;

    // 第一行
    QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
    // 检测等待图标
    QLabel *loadingGif = new QLabel(centerFont);
    loadingGif->setFixedSize(24,24);
    // 环境检测等待动画
    QMovie *movie = new QMovie(":/images/loading.gif", QByteArray(), centerFont);
    loadingGif->setMovie(movie);
    hlayoutCenterFont1->addWidget(loadingGif);
    // 检测结果对错图标
    PixmapLabel *resultLogo = new PixmapLabel(centerFont);
    resultLogo->setFixedSize(24,24);
    hlayoutCenterFont1->addWidget(resultLogo);
    // 检测中大标题
    MyLabel *bigTitle = new MyLabel(centerFont);
    bigTitle->setFontSize(24);
    bigTitle->setIsOriginal(true);
    bigTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    hlayoutCenterFont1->addWidget(bigTitle);
    hlayoutCenterFont1->setAlignment(Qt::AlignLeft);
    vlayoutCenterFont->addLayout(hlayoutCenterFont1);
    vlayoutCenterFont->addSpacing(16);

    // 第二行
    QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
    hlayoutCenterFont2->addSpacing(10);
    // 检测中的记录：黑点1和文字1
    CircleLable *dot1 = new CircleLable(QString(""), centerFont, 6, Qt::black);
    hlayoutCenterFont2->addWidget(dot1);
    hlayoutCenterFont2->addSpacing(5);
    MyLabel *labelCheck1 = new MyLabel(centerFont);
    labelCheck1->setIsOriginal(true);
    labelCheck1->setWordWrap(true);
    labelCheck1->adjustSize();
    labelCheck1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    hlayoutCenterFont2->addWidget(labelCheck1);
    hlayoutCenterFont2->setAlignment(Qt::AlignLeft);
    vlayoutCenterFont->addLayout(hlayoutCenterFont2);

    // 第三行
    QHBoxLayout *hlayoutCenterFont3 = new QHBoxLayout;
    hlayoutCenterFont3->addSpacing(10);
    // 检测中的记录：黑点2和文字2
    CircleLable *dot2 = new CircleLable(QString(""), centerFont, 6, Qt::black);
    hlayoutCenterFont3->addWidget(dot2);
    hlayoutCenterFont3->addSpacing(5);
    MyLabel *labelCheck2 = new MyLabel(centerFont);
    labelCheck2->setIsOriginal(true);
    labelCheck2->setWordWrap(true);
    labelCheck2->adjustSize();
    labelCheck2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    hlayoutCenterFont3->addWidget(labelCheck2);
    hlayoutCenterFont3->setAlignment(Qt::AlignLeft);
    vlayoutCenterFont->addLayout(hlayoutCenterFont3);

    // 第四行
    vlayoutCenterFont->addSpacing(56);

    // 第五行
    QHBoxLayout *hlayoutCenterFont5 = new QHBoxLayout;
    hlayoutCenterFont5->setSpacing(16);
    hlayoutCenterFont5->addStretch();
    // 上一步按钮
    KBorderButton *preStep = new KBorderButton(centerFont);
    preStep->setText(tr("Back"));
    preStep->setEnabled(true);
    preStep->setAutoRepeat(true);
    connect(preStep, &KBorderButton::clicked, preStep, &KBorderButton::clearFocus);
    connect(preStep, &KBorderButton::clicked, this, &SystemRestore::on_pre_clicked);
    hlayoutCenterFont5->addWidget(preStep);
    // 下一步按钮
    MyPushButton *nextStep = new MyPushButton(centerFont);
    nextStep->setText(tr("Next"));
    nextStep->setEnabled(true);
    nextStep->setAutoRepeat(true);
    nextStep->setProperty("isImportant", true);
    connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
        this->on_next_clicked(checked);
        emit this->startRestore();
    });
    hlayoutCenterFont5->addWidget(nextStep);
    // 重新检测按钮
    MyPushButton *recheck = new MyPushButton(centerFont);
    recheck->setText(tr("Recheck"));
    recheck->setEnabled(true);
    recheck->setAutoRepeat(true);
    recheck->setProperty("isImportant", true);
    hlayoutCenterFont5->addWidget(recheck);
    hlayoutCenterFont5->addStretch();
    hlayoutCenterFont5->setAlignment(Qt::AlignCenter);
    vlayoutCenterFont->addLayout(hlayoutCenterFont5);

    centerFont->setLayout(vlayoutCenterFont);
    QHBoxLayout *layoutLine3 = new QHBoxLayout;
    layoutLine3->addStretch();
    layoutLine3->addSpacing(80);
    layoutLine3->addWidget(centerFont);
    layoutLine3->addSpacing(80);
    layoutLine3->addStretch();
    layoutLine3->setAlignment(Qt::AlignCenter);

    // ------------ 中部布局end-------------

    // 布局
    QVBoxLayout *vlayout = new QVBoxLayout;
    vlayout->addSpacing(40);
    vlayout->addLayout(layoutLine1);
    vlayout->addLayout(layoutLine2);
    vlayout->addSpacing(80);
    vlayout->addLayout(layoutLine3);
    vlayout->addStretch();
    second->setLayout(vlayout);

    // 开始检测
    connect(this, &SystemRestore::startCheckEnv, this, [=]() {
        this->m_systemRestoreState = SystemRestoreState::CHECKING;
        loadingGif->setVisible(true);
        movie->start();
        resultLogo->setVisible(false);
        // 环境检测中，请等待
        bigTitle->setDeplayText(tr("Checking, wait a moment ..."));
        dot1->setBackgroundColor(Qt::black);
        dot2->setBackgroundColor(Qt::black);
        labelCheck1->setFontColor(Qt::black);
        labelCheck2->setFontColor(Qt::black);
        // 还原过程中不要做其它操作，以防数据丢失
        labelCheck1->setDeplayText(tr("Check whether the restore environment meets the requirements"));
        // 检测还原环境是否满足
        labelCheck2->setDeplayText(tr("Do not perform other operations during restore to avoid data loss"));
        preStep->setVisible(false);
        nextStep->setVisible(false);
        recheck->setVisible(false);

        this->on_checkEnv_start();
        emit GlobelBackupInfo::inst().getGlobalSignals()->widthChanged();
    });

    // 检测结果
    connect(this, &SystemRestore::checkEnvResult, this, [=](bool result, const QString &errMsg, const QString &errTip) {
        loadingGif->setVisible(false);
        movie->stop();

        if (result) {
            resultLogo->setThemeIconSchema("ukui-dialog-success", ":/symbos/ukui-dialog-success");
            resultLogo->setVisible(true);
            // 检测成功
            bigTitle->setDeplayText(tr("Check success"));
            // 还原完成后将自动重启
            labelCheck1->setDeplayText(tr("The system will reboot automatically after the restore is successful"));
            dot2->setBackgroundColor(COLOR_YELLOW);
            labelCheck2->setFontColor(COLOR_YELLOW);
            labelCheck2->setFontWordWrap(true);
            // 请确保电脑已连接电源或电量超过60%
            labelCheck2->setDeplayText(tr("Make sure the computer is plugged in or the battery level is above 60%"));
            dot1->setVisible(true);
            dot2->setVisible(true);
            labelCheck1->setVisible(true);
            labelCheck2->setVisible(true);
            nextStep->setVisible(true);
            recheck->setVisible(false);
        } else {
            resultLogo->setThemeIconSchema("dialog-error", ":/symbos/dialog-error");
            resultLogo->setVisible(true);
            // 环境校验失败
            bigTitle->setDeplayText(tr("Check failure"));
            labelCheck1->setDeplayText(errMsg);
            labelCheck2->setDeplayText(errTip);
            if (errMsg.isEmpty()) {
                dot1->setVisible(false);
                labelCheck1->setVisible(false);
            } else {
                dot1->setVisible(true);
                labelCheck1->setVisible(true);
            }
            if (errTip.isEmpty()) {
                dot2->setVisible(false);
                labelCheck2->setVisible(false);
            } else {
                dot2->setVisible(true);
                labelCheck2->setVisible(true);
            }
            recheck->setVisible(true);
            nextStep->setVisible(false);
        }

        preStep->setVisible(true);
        emit GlobelBackupInfo::inst().getGlobalSignals()->widthChanged();
    });

    // 调整中部控件大小
    connect(GlobelBackupInfo::inst().getGlobalSignals(), &GlobalSignals::widthChanged, this, [=](){
        // 控件bigTitle的宽度
        int len_title = 0;
        if (bigTitle->isVisible()) {
            QFontMetrics fontMetrics(bigTitle->font());
            len_title = fontMetrics.width(bigTitle->getOriginalText());
            len_title += LEN_TITLE_PRE;
        }
        // 控件labelError1的宽度
        int len_labelError1 = 0;
        if (labelCheck1->isVisible()) {
            QFontMetrics fontMetrics(labelCheck1->font());
            len_labelError1 = fontMetrics.width(labelCheck1->getOriginalText());
            len_labelError1 += LEN_DOT_PRE;
        }
        // 控件labelError2的宽度
        int len_labelError2 = 0;
        if (labelCheck2->isVisible()) {
            QFontMetrics fontMetrics(labelCheck2->font());
            len_labelError2 = fontMetrics.width(labelCheck2->getOriginalText());
            len_labelError2 += LEN_DOT_PRE;
        }
        int len_max = len_title > len_labelError1 ? len_title : len_labelError1;
        len_max = len_max > len_labelError2 ? len_max : len_labelError2;
        if (len_max >= this->width())
            len_max = this->width();

        centerFont->setFixedWidth(len_max);
    });

    // 重新检查
    connect(recheck, &MyPushButton::clicked, this, [=](bool checked) {
        Q_UNUSED(checked)
        emit this->startCheckEnv();
    });

    addWidget(second);
}

/**
 * @brief 开始进行环境检测
 */
void SystemRestore::on_checkEnv_start()
{
    GlobelBackupInfo::inst().setIsBusy(true);
    m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
    connect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkEnv_end);

    // 是否已存在备份、还原等操作
    bool isActive = false;
    if(int(BackupState::BACKUP_STATE_INIT) != m_pInterface->getBackupState(isActive)){
        on_checkEnv_end(int(BackupResult::OTHER_BACKUP_OR_RESTORE_RUNNING));

        return;
    }

    BackupWrapper backupWrapper;
    backupWrapper.m_type = m_isRetainUserData ? BackupType::RESTORE_SYSTEM_WITH_DATA : BackupType::RESTORE_SYSTEM;
    backupWrapper.m_iPosition = m_iPosition;
    backupWrapper.m_uuid = m_uuid;
    backupWrapper.m_backupName = m_backupName;
    backupWrapper.m_prefixDestPath = m_devPath;
    backupWrapper.m_isOtherMachine = m_isOtherMachine ? 1 : 0;
    backupWrapper.m_frontUid = getuid();
    backupWrapper.m_frontUserName = qgetenv("USER");
    backupWrapper.m_gid = getgid();
    m_pInterface->checkEnv(backupWrapper);
}

/**
 * @brief 环境检测结束
 * @param result, 环境校验结果
 */
void SystemRestore::on_checkEnv_end(int result)
{
    m_systemRestoreState = SystemRestoreState::IDEL;
    bool bRst = false;
    QString errMsg, errTip;
    switch (result) {
    case int(BackupResult::LOCK_PROGRAM_FAIL):
        // 程序锁定失败，请重试
        errMsg = tr("Program lock failed, please retry");
        // 可能有其它备份/还原等任务在执行
        errTip = tr("There may be other backups or restores being performed");
        break;
    case int(BackupResult::NO_FOUND_DEALCLASS):
        // 不支持的任务类型
        errMsg = tr("Unsupported task type");
        // 没有找到相应的处理逻辑
        errTip = tr("No processing logic was found in the service");
        break;
    case int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED):
        // ".user.txt文件不存在"
        errMsg = tr("The .user.txt file does not exist");
        // 备份点可能被损坏
        errTip = tr("Backup points may be corrupted");
        break;
    case int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED):
        // .exclude.user.txt文件不存在
        errMsg = tr("The .exclude.user.txt file does not exist");
        // 备份点可能被损坏
        errTip = tr("Backup points may be corrupted");
        break;
    case int(BackupResult::INC_NOT_FOUND_DIR):
        // 备份点数据目录不存在
        errMsg = tr("The backup point data directory does not exist");
        // 备份点可能被损坏
        errTip = tr("Backup points may be corrupted");
        break;
    case int(BackupResult::EFI_RSYNC_FAIL):
        // 同步/boot/efi失败
        errMsg = tr("Failed to rsync /boot/efi");
        // 请检查/boot/efi分区挂载方式
        errTip = tr("Check the mounting mode of the /boot/efi partition");
        break;
    default:
        bRst = true;
        break;
    }

    Utils::wait(2);
    emit checkEnvResult(bRst, errMsg, errTip);
    GlobelBackupInfo::inst().setIsBusy(false);
    disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkEnv_end);
    delete m_pInterface;
    m_pInterface = nullptr;
}

/**
 * @brief 第三个页面-还原中
 */
void SystemRestore::initThirdWidget()
{
    QWidget *third = new QWidget;

    // 流程进度提示栏
    CircleLable *one = new CircleLable("1", third, 24, QColor(COLOR_BLUE));
    LineLabel *line1 = new LineLabel(third, QColor(COLOR_BLUE));
    CircleLable *two = new CircleLable("2", third, 24, QColor(COLOR_BLUE));
    LineLabel *line2 = new LineLabel(third, QColor(COLOR_BLUE));
    CircleLable *three = new CircleLable("3", third);
    QHBoxLayout *layoutLine1 = new QHBoxLayout;
    layoutLine1->addSpacing(128);
    layoutLine1->addWidget(one);
    layoutLine1->addWidget(line1);
    layoutLine1->addWidget(two);
    layoutLine1->addWidget(line2);
    layoutLine1->addWidget(three);
    layoutLine1->addSpacing(128);

    MyLabel *label1 = new MyLabel(tr("checking"), third);
    label1->setIsOriginal(true);
    label1->setFontColor(QColor(COLOR_BLUE));
    label1->setFixedWidth(164);
    MyLabel *label2 = new MyLabel(tr("restoring"), third);
    label2->setIsOriginal(true);
    label2->setFontColor(QColor(COLOR_BLUE));
    label2->setFixedWidth(164);
    MyLabel *label3 = new MyLabel(tr("finished"), third);
    label3->setIsOriginal(true);
    label3->setEnabled(false);
    label3->setFixedWidth(164);
    QHBoxLayout *layoutLine2 = new QHBoxLayout;
    layoutLine2->addSpacing(54);
    layoutLine2->addWidget(label1);
    layoutLine2->addStretch();
    layoutLine2->addWidget(label2);
    layoutLine2->addStretch();
    layoutLine2->addWidget(label3);
    layoutLine2->addSpacing(54);

    // ------------ 中部布局begin-------------
    // 中部第一行
    QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
    // 检测等待图标
    QLabel *loadingGif = new QLabel(third);
    // 环境检测等待动画
    QMovie *movie = new QMovie(":/images/loading.gif", QByteArray(), third);
    loadingGif->setMovie(movie);
    loadingGif->setVisible(false);
    // 进度条
    RingsProgressbar *progressBar = new RingsProgressbar(third);
    progressBar->setFixedSize(100, 100);
    hlayoutCenterFont1->addStretch();
    hlayoutCenterFont1->addWidget(loadingGif);
    hlayoutCenterFont1->addWidget(progressBar);
    hlayoutCenterFont1->addStretch();
    hlayoutCenterFont1->setAlignment(Qt::AlignCenter);

    // 第二行
    QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
    // 提醒
    MyLabel *labelTip = new MyLabel(third);
    labelTip->setAlignment(Qt::AlignCenter);
    labelTip->setIsOriginal(true);
    labelTip->setFontWordWrap(true);
    labelTip->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    // 不要使用电脑，以防数据丢失
    labelTip->setDeplayText(tr("Do not use computer in case of data loss"));
    hlayoutCenterFont2->addStretch();
    hlayoutCenterFont2->addWidget(labelTip);
    hlayoutCenterFont2->addStretch();
    hlayoutCenterFont2->setAlignment(Qt::AlignCenter);

    // ------------ 中部布局end-------------

    // 布局
    QVBoxLayout *vlayout = new QVBoxLayout;
    vlayout->addSpacing(40);
    vlayout->addLayout(layoutLine1);
    vlayout->addLayout(layoutLine2);
    vlayout->addSpacing(80);
    vlayout->addLayout(hlayoutCenterFont1);
    vlayout->addSpacing(16);
    vlayout->addLayout(hlayoutCenterFont2);
    vlayout->addStretch();
    third->setLayout(vlayout);

    // 开始还原
    connect(this, &SystemRestore::startRestore, this, [=] {
        progressBar->setPersent(0);
        movie->start();

        // 开始还原
        this->on_restore_start();
    });

    // 进度
    connect(this, &SystemRestore::progress, this, [=](int state, int rate) {
        Q_UNUSED(state)
        progressBar->setPersent(rate);
    });

    addWidget(third);
}

/**
 * @brief 开始还原
 */
void SystemRestore::on_restore_start()
{
    GlobelBackupInfo::inst().setIsBusy(true);
    m_systemRestoreState = SystemRestoreState::RESTORING;
    m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
    connect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkRestore_end);
    connect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemRestore::progress);
    connect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &SystemRestore::on_restore_end);

    // 是否已存在备份、还原等操作
    bool isActive = false;
    if(int(BackupState::BACKUP_STATE_INIT) != m_pInterface->getBackupState(isActive)){
        on_checkEnv_end(int(BackupResult::OTHER_BACKUP_OR_RESTORE_RUNNING));

        return;
    }

    BackupWrapper backupWrapper;
    backupWrapper.m_type = m_isRetainUserData ? BackupType::RESTORE_SYSTEM_WITH_DATA : BackupType::RESTORE_SYSTEM;
    backupWrapper.m_iPosition = m_iPosition;
    backupWrapper.m_uuid = m_uuid;
    backupWrapper.m_backupName = m_backupName;
    backupWrapper.m_prefixDestPath = m_devPath;
    backupWrapper.m_isOtherMachine = m_isOtherMachine ? 1 : 0;
    backupWrapper.m_frontUid = getuid();
    backupWrapper.m_frontUserName = qgetenv("USER");
    backupWrapper.m_gid = getgid();
    m_pInterface->goRestore(backupWrapper);
}

/**
 * @brief 系统还原校验结果处理
 * @param result
 */
void SystemRestore::on_checkRestore_end(int result)
{
    bool bRst = false;
    QString errMsg, errTip;
    switch (result) {
    case int(BackupResult::LOCK_PROGRAM_FAIL):
        // 程序锁定失败，请重试
        errMsg = tr("Program lock failed, please retry");
        // 可能有其它备份/还原等任务在执行
        errTip = tr("There may be other backups or restores being performed");
        break;
    case int(BackupResult::NO_FOUND_DEALCLASS):
        // 不支持的任务类型
        errMsg = tr("Unsupported task type");
        // 没有找到相应的处理逻辑
        errTip = tr("No processing logic was found in the service");
        break;
    case int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED):
        // ".user.txt文件不存在"
        errMsg = tr("The .user.txt file does not exist");
        // 备份点可能被损坏
        errTip = tr("Backup points may be corrupted");
        break;
    case int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED):
        // .exclude.user.txt文件不存在
        errMsg = tr("The .exclude.user.txt file does not exist");
        // 备份点可能被损坏
        errTip = tr("Backup points may be corrupted");
        break;
    case int(BackupResult::INC_NOT_FOUND_DIR):
        // 备份点数据目录不存在
        errMsg = tr("The backup point data directory does not exist");
        // 备份点可能被损坏
        errTip = tr("Backup points may be corrupted");
        break;
    case int(BackupResult::EFI_RSYNC_FAIL):
        // 同步/boot/efi失败
        errMsg = tr("Failed to rsync /boot/efi");
        // 请检查/boot/efi分区挂载方式
        errTip = tr("Check the mounting mode of the /boot/efi partition");
        break;
    case int(BackupResult::RESTOREDIR_PREPARE_FAILED):
        // 还原目录准备失败
        errMsg = tr("Failed to prepare the restore directory");
        // 更多信息请参考日志/var/log/backup.log
        errTip = tr("Refer to log :/var/log/backup.log for more information");
        break;
    default:
        bRst = true;
        break;
    }

    if (!bRst) {
        GlobelBackupInfo::inst().setIsBusy(false);
        m_systemRestoreState = SystemRestoreState::IDEL;
        this->on_next_clicked(true);
        emit this->checkRestoreResult(bRst, errMsg, errTip);
        disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkRestore_end);
        disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemRestore::progress);
        disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &SystemRestore::on_restore_end);
        delete m_pInterface;
        m_pInterface = nullptr;
    }
}

/**
 * @brief 系统还原结束
 * @param result-false 失败; true 成功
 */
void SystemRestore::on_restore_end(bool result)
{
    m_systemRestoreState = SystemRestoreState::IDEL;

    this->on_next_clicked(true);
    if (result) {
        emit checkRestoreResult(result);
    } else {
        // 还原过程中出现错误
        QString errMsg = tr("An error occurred during restore");
        // 错误信息参考日志文件：/var/log/backup.log
        QString errTip = tr("Error messages refer to log file : /var/log/backup.log");
        emit checkRestoreResult(result, errMsg, errTip);
    }

    GlobelBackupInfo::inst().setIsBusy(false);
    disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkRestore_end);
    disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemRestore::progress);
    disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &SystemRestore::on_restore_end);
    delete m_pInterface;
    m_pInterface = nullptr;
}

/**
 * @brief 初始化最后一页
 */
void SystemRestore::initLastWidget()
{
    QWidget *last = new QWidget;

    // 流程进度提示栏
    CircleLable *one = new CircleLable("1", last, 24, QColor(COLOR_BLUE));
    LineLabel *line1 = new LineLabel(last, QColor(COLOR_BLUE));
    CircleLable *two = new CircleLable("2", last, 24, QColor(COLOR_BLUE));
    LineLabel *line2 = new LineLabel(last, QColor(COLOR_BLUE));
    CircleLable *three = new CircleLable("3", last, 24, QColor(COLOR_BLUE));
    QHBoxLayout *layoutLine1 = new QHBoxLayout;
    layoutLine1->addSpacing(128);
    layoutLine1->addWidget(one);
    layoutLine1->addWidget(line1);
    layoutLine1->addWidget(two);
    layoutLine1->addWidget(line2);
    layoutLine1->addWidget(three);
    layoutLine1->addSpacing(128);

    MyLabel *label1 = new MyLabel(tr("checking"), last);
    label1->setIsOriginal(true);
    label1->setFontColor(QColor(COLOR_BLUE));
    label1->setFixedWidth(164);
    MyLabel *label2 = new MyLabel(tr("restoring"), last);
    label2->setIsOriginal(true);
    label2->setFontColor(QColor(COLOR_BLUE));
    label2->setFixedWidth(164);
    MyLabel *label3 = new MyLabel(tr("finished"), last);
    label3->setIsOriginal(true);
    label3->setFontColor(QColor(COLOR_BLUE));
    label3->setFixedWidth(164);
    QHBoxLayout *layoutLine2 = new QHBoxLayout;
    layoutLine2->addSpacing(54);
    layoutLine2->addWidget(label1);
    layoutLine2->addStretch();
    layoutLine2->addWidget(label2);
    layoutLine2->addStretch();
    layoutLine2->addWidget(label3);
    layoutLine2->addSpacing(54);

    // ------------ 中部布局begin-------------
    QWidget *centerFont = new QWidget(last);
    centerFont->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    QVBoxLayout *vlayoutCenterFont = new QVBoxLayout;

    // 中部第一行
    QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
    // 备份结果对错图标
    PixmapLabel *resultLogo = new PixmapLabel(centerFont);
    resultLogo->setFixedSize(24,24);
    hlayoutCenterFont1->addWidget(resultLogo);
    // 检测中大标题
    MyLabel *bigTitle = new MyLabel(centerFont);
    bigTitle->setFontSize(24);
    bigTitle->setIsOriginal(true);
    bigTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    hlayoutCenterFont1->addWidget(bigTitle);
    hlayoutCenterFont1->setAlignment(Qt::AlignLeft);
    vlayoutCenterFont->addLayout(hlayoutCenterFont1);
    vlayoutCenterFont->addSpacing(16);

    // 第二行
    QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
    hlayoutCenterFont2->addSpacing(10);
    // 备份结果错误提示：黑点和文字
    CircleLable *dot1 = new CircleLable(QString(""), centerFont, 6, Qt::black);
    hlayoutCenterFont2->addWidget(dot1);
    hlayoutCenterFont2->addSpacing(5);
    MyLabel *labelError1 = new MyLabel(centerFont);
    labelError1->setIsOriginal(true);
    labelError1->setWordWrap(true);
    labelError1->adjustSize();
    labelError1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    hlayoutCenterFont2->addWidget(labelError1);
    hlayoutCenterFont2->setAlignment(Qt::AlignLeft);
    vlayoutCenterFont->addLayout(hlayoutCenterFont2);

    // 第三行
    QHBoxLayout *hlayoutCenterFont3 = new QHBoxLayout;
    hlayoutCenterFont3->addSpacing(10);
    // 检测中的记录：黑点2和文字2
    CircleLable *dot2 = new CircleLable(QString(""), centerFont, 6, Qt::black);
    hlayoutCenterFont3->addWidget(dot2);
    hlayoutCenterFont3->addSpacing(5);
    MyLabel *labelError2 = new MyLabel(centerFont);
    labelError2->setIsOriginal(true);
    labelError2->setWordWrap(true);
    labelError2->adjustSize();
    labelError2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    hlayoutCenterFont3->addWidget(labelError2);
    hlayoutCenterFont3->setAlignment(Qt::AlignLeft);
    vlayoutCenterFont->addLayout(hlayoutCenterFont3);

    // 第四行
    vlayoutCenterFont->addSpacing(56);

    // 第五行
    QHBoxLayout *hlayoutCenterFont5 = new QHBoxLayout;
    hlayoutCenterFont5->setSpacing(16);
    hlayoutCenterFont5->addStretch();
    // 返回首页
    MyPushButton *homePage = new MyPushButton(centerFont);
    homePage->setText(tr("Home Page"));
    homePage->setEnabled(true);
    homePage->setAutoRepeat(true);
    homePage->setProperty("isImportant", true);
    hlayoutCenterFont5->addWidget(homePage);
    // 再试一次
    KBorderButton *retry = new KBorderButton(centerFont);
    retry->setText(tr("Retry"));
    retry->setEnabled(true);
    retry->setAutoRepeat(true);
    hlayoutCenterFont5->addWidget(retry);
    hlayoutCenterFont5->addStretch();
    hlayoutCenterFont5->setAlignment(Qt::AlignCenter);
    vlayoutCenterFont->addLayout(hlayoutCenterFont5);

    centerFont->setLayout(vlayoutCenterFont);
    QHBoxLayout *layoutLine3 = new QHBoxLayout;
    layoutLine3->addStretch();
    layoutLine3->addSpacing(80);
    layoutLine3->addWidget(centerFont);
    layoutLine3->addSpacing(80);
    layoutLine3->addStretch();
    // ------------ 中部布局end-------------

    // 布局
    QVBoxLayout *vlayout = new QVBoxLayout;
    vlayout->addSpacing(40);
    vlayout->addLayout(layoutLine1);
    vlayout->addLayout(layoutLine2);
    vlayout->addSpacing(80);
    vlayout->addLayout(layoutLine3);
    vlayout->addStretch();
    last->setLayout(vlayout);

    // 还原检测结果
    connect(this, &SystemRestore::checkRestoreResult, this, [=](bool result, const QString &errMsg, const QString &errTip) {
        if (result) {
            resultLogo->setThemeIconSchema("ukui-dialog-success", ":/symbos/ukui-dialog-success");
            resultLogo->setVisible(true);
            // 系统还原成功
            bigTitle->setDeplayText(tr("Successfully restoring the system"));
            dot1->setVisible(true);
            dot2->setVisible(false);
            labelError1->setVisible(true);
            // 系统将自动重启
            labelError1->setDeplayText(tr("The system will automatically reboot"));
            labelError2->setVisible(false);
            retry->setVisible(false);
            homePage->setVisible(false);
        } else {
            resultLogo->setThemeIconSchema("dialog-error", ":/symbos/dialog-error");
            resultLogo->setVisible(true);
            // 系统还原失败
            bigTitle->setDeplayText(tr("Restoring the system failed"));
            dot1->setVisible(true);
            dot2->setVisible(true);
            labelError1->setVisible(true);
            labelError2->setVisible(true);
            labelError1->setDeplayText(errMsg);
            labelError2->setDeplayText(errTip);
            retry->setVisible(true);
            homePage->setVisible(true);
        }
        emit GlobelBackupInfo::inst().getGlobalSignals()->widthChanged();
    });

    // 调整中部控件大小
    connect(GlobelBackupInfo::inst().getGlobalSignals(), &GlobalSignals::widthChanged, this, [=](){
        // 控件bigTitle的宽度
        int len_title = 0;
        if (bigTitle->isVisible()) {
            QFontMetrics fontMetrics(bigTitle->font());
            len_title = fontMetrics.width(bigTitle->getOriginalText());
            len_title += LEN_TITLE_PRE;
        }
        // 控件labelError1的宽度
        int len_labelError1 = 0;
        if (labelError1->isVisible()) {
            QFontMetrics fontMetrics(labelError1->font());
            len_labelError1 = fontMetrics.width(labelError1->getOriginalText());
            len_labelError1 += LEN_DOT_PRE;
        }
        // 控件labelError2的宽度
        int len_labelError2 = 0;
        if (labelError2->isVisible()) {
            QFontMetrics fontMetrics(labelError2->font());
            len_labelError2 = fontMetrics.width(labelError2->getOriginalText());
            len_labelError2 += LEN_DOT_PRE;
        }
        int len_max = len_title > len_labelError1 ? len_title : len_labelError1;
        len_max = len_max > len_labelError2 ? len_max : len_labelError2;
        if (len_max >= this->width())
            len_max = this->width();

        centerFont->setFixedWidth(len_max);
    });

    // 再试一次
    connect(retry, &KBorderButton::clicked, this, [=](bool checked) {
        Q_UNUSED(checked)
        retry->clearFocus();
        this->setCurrentIndex(SystemRestorePage::RESTORE_PAGE);
        emit this->startRestore();
    });

    // 返回首页
    connect(homePage, &MyPushButton::clicked, this, [=](bool checked) {
        Q_UNUSED(checked)
        this->setCurrentIndex(SystemRestorePage::HOME_PAGE);
    });

    addWidget(last);
}



